home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / gsview / src / gvwprn.c < prev    next >
C/C++ Source or Header  |  1995-11-30  |  45KB  |  1,510 lines

  1. /* Copyright (C) 1993, 1994, Russell Lang.  All rights reserved.
  2.   
  3.   This file is part of GSview.
  4.   
  5.   This program is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the GSview Free Public Licence 
  9.   (the "Licence") for full details.
  10.   
  11.   Every copy of GSview must include a copy of the Licence, normally in a 
  12.   plain ASCII text file named LICENCE.  The Licence grants you the right 
  13.   to copy, modify and redistribute GSview, but only under certain conditions 
  14.   described in the Licence.  Among other things, the Licence requires that 
  15.   the copyright notice and this notice be preserved on all copies.
  16. */
  17.  
  18. /* gvwprn.c */
  19. /* Printer routines for Windows GSview */
  20. #include "gvwin.h"
  21.  
  22.  
  23. /* documented in Device Driver Adaptation Guide */
  24. /* Prototypes taken from print.h */
  25. DECLARE_HANDLE(HPJOB);
  26.  
  27. HPJOB   WINAPI OpenJob(LPSTR, LPSTR, HPJOB);
  28. int     WINAPI StartSpoolPage(HPJOB);
  29. int     WINAPI EndSpoolPage(HPJOB);
  30. int     WINAPI WriteSpool(HPJOB, LPSTR, int);
  31. int     WINAPI CloseJob(HPJOB);
  32. int     WINAPI DeleteJob(HPJOB, int);
  33. int     WINAPI WriteDialog(HPJOB, LPSTR, int);
  34. int     WINAPI DeleteSpoolPage(HPJOB);
  35.  
  36. static char pcfname[MAXSTR];    /* name of temporary command file for printing */
  37. static char pfname[MAXSTR];    /* name of temporary file for printing options */
  38. char not_defined[] = "[Not defined]";
  39. char * get_ports(void);
  40. #define PORT_BUF_SIZE 4096
  41.  
  42. void
  43. strip_spaces(char *s)
  44. {
  45. char *d = s;
  46.    while (*s) {
  47.     if (*s != ' ')
  48.         *d++ = *s;
  49.     s++;
  50.    }
  51.    *d = '\0';
  52. }
  53.  
  54. char editpropname[MAXSTR];
  55.  
  56. /* dialog for adding or editing properties */
  57. BOOL CALLBACK _export
  58. EditPropDlgProc(HWND hDlg, UINT wmsg, WPARAM wParam, LPARAM lParam)
  59. {
  60. static char device[MAXSTR];    /* contains printer device name */
  61.     switch (wmsg) {
  62.     case WM_INITDIALOG:
  63.         lstrcpy(device, (LPSTR)lParam);    /* initialise device name */
  64.         if (*editpropname) {
  65.         char section[MAXSTR];
  66.         char buf[MAXSTR];
  67.         if (*editpropname == 's')
  68.             SendDlgItemMessage(hDlg, EDITPROP_STRING, BM_SETCHECK, 
  69.                 (WPARAM)1, 0L);
  70.         else
  71.             SendDlgItemMessage(hDlg, EDITPROP_NUMBER, BM_SETCHECK, 
  72.                 (WPARAM)1, 0L);
  73.         SetDlgItemText(hDlg, EDITPROP_NAME, editpropname+1);
  74.         strcpy(section, device);
  75.         strcat(section, " values");
  76.         GetPrivateProfileString(section, editpropname, "", buf, sizeof(buf)-2, INIFILE);
  77.         SetDlgItemText(hDlg, EDITPROP_VALUE, buf);
  78.         }
  79.         else
  80.             SendDlgItemMessage(hDlg, EDITPROP_NUMBER, BM_SETCHECK, (WPARAM)1, 0L);
  81.         return TRUE;
  82.     case WM_COMMAND:
  83.       switch (LOWORD(wParam)) {
  84.         case EDITPROP_DEL:
  85.         {
  86.         char name[MAXSTR];
  87.         char section[MAXSTR];
  88.         if ( SendDlgItemMessage(hDlg, EDITPROP_STRING, 
  89.             BM_GETCHECK, (WPARAM)1, 0L) > 0) {
  90.             strcpy(name, "s");
  91.         }
  92.         else
  93.             strcpy(name, "d");
  94.         GetDlgItemText(hDlg, EDITPROP_NAME, name+1, sizeof(name)-2);
  95.         strip_spaces(name);
  96.         if (strlen(name)>1) {
  97.             strcpy(section, device);
  98.             strcat(section, " values");
  99.             WritePrivateProfileString(section, name, NULL, INIFILE);
  100.             WritePrivateProfileString(device, name, NULL, INIFILE);
  101.         }
  102.         EndDialog(hDlg, TRUE);
  103.         }
  104.         return TRUE;
  105.         case ID_HELP:
  106.         SendMessage(hwndimg, help_message, 0, 0L);
  107.         return(FALSE);
  108.         case IDOK:
  109.         {
  110.         char name[MAXSTR];
  111.         char value[MAXSTR];
  112.         char section[MAXSTR];
  113.         if ( SendDlgItemMessage(hDlg, EDITPROP_STRING, 
  114.             BM_GETCHECK, (WPARAM)1, 0L) > 0) {
  115.             strcpy(name, "s");
  116.         }
  117.         else
  118.             strcpy(name, "d");
  119.         GetDlgItemText(hDlg, EDITPROP_NAME, name+1, sizeof(name)-2);
  120.         GetDlgItemText(hDlg, EDITPROP_VALUE, value, sizeof(value)-1);
  121.         strip_spaces(name);
  122.         strip_spaces(value);
  123.         if ((strlen(name)>1) && strlen(value)) {
  124.             strcpy(section, device);
  125.             strcat(section, " values");
  126.             WritePrivateProfileString(section, name, value, INIFILE);
  127.             strtok(value, ",");
  128.             WritePrivateProfileString(device, name, value, INIFILE);
  129.         }
  130.         EndDialog(hDlg, TRUE);
  131.         }
  132.         return TRUE;
  133.         case IDCANCEL:
  134.         EndDialog(hDlg, FALSE);
  135.         return TRUE;
  136.       }
  137.       break;
  138.     }
  139.     return FALSE;
  140. }
  141.  
  142. /* dialog box for selecting printer properties */
  143. BOOL CALLBACK _export
  144. PropDlgProc(HWND hDlg, UINT wmsg, WPARAM wParam, LPARAM lParam)
  145. {
  146.     char buf[128];
  147.     int iprop;
  148.     int ivalue;
  149.     WORD notify_message;
  150.     char *p;
  151.     char *value;
  152.     static char device[MAXSTR];    /* contains printer device name */
  153.     static struct prop_item_s* propitem;
  154.     char section[MAXSTR];
  155.  
  156.     switch (wmsg) {
  157.     case WM_INITDIALOG:
  158.         lstrcpy(device, (LPSTR)lParam);    /* initialise device name */
  159.         propitem = get_properties(device);
  160.         SendDlgItemMessage(hDlg, PROP_NAME, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
  161.         SendDlgItemMessage(hDlg, PROP_VALUE, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
  162.         for (iprop=0; propitem[iprop].name[0]; iprop++) {
  163.         SendDlgItemMessage(hDlg, PROP_NAME, CB_ADDSTRING, 0, 
  164.             (LPARAM)((LPSTR)propitem[iprop].name+1));
  165.         }
  166.         SendDlgItemMessage(hDlg, PROP_NAME, CB_SETCURSEL, 0, 0L);
  167.         /* force update of PROP_VALUE */
  168.         SendDlgNotification(hDlg, PROP_NAME, CBN_SELCHANGE);
  169.         EnableWindow(GetDlgItem(hDlg, PROP_NAME), (iprop != 0));
  170.         EnableWindow(GetDlgItem(hDlg, PROP_VALUE), (iprop != 0));
  171.         EnableWindow(GetDlgItem(hDlg, PROP_EDIT), (iprop != 0));
  172.  
  173.         if (option.gsversion < IDM_GS351) {
  174.         EnableWindow(GetDlgItem(hDlg, PROP_XOFFSET), FALSE);
  175.         EnableWindow(GetDlgItem(hDlg, PROP_YOFFSET), FALSE);
  176.         }
  177.         else {
  178.         strcpy(section, device);
  179.         strcat(section, " PageOffset");
  180.         GetPrivateProfileString(section, "X", "0", buf, sizeof(buf)-2, INIFILE);
  181.         SetDlgItemText(hDlg, PROP_XOFFSET, buf);
  182.         GetPrivateProfileString(section, "Y", "0", buf, sizeof(buf)-2, INIFILE);
  183.         SetDlgItemText(hDlg, PROP_YOFFSET, buf);
  184.         }
  185.  
  186.         SetFocus(GetDlgItem(hDlg, IDOK));
  187.         return TRUE;
  188.     case WM_COMMAND:
  189.         notify_message = GetNotification(wParam,lParam);
  190.         switch (LOWORD(wParam)) {
  191.         case ID_HELP:
  192.             load_string(IDS_TOPICPROP, szHelpTopic, sizeof(szHelpTopic));
  193.             SendMessage(hwndimg, help_message, 0, 0L);
  194.             load_string(IDS_TOPICPRINT, szHelpTopic, sizeof(szHelpTopic));
  195.             return(FALSE);
  196.         case PROP_NAME:
  197.             if (notify_message != CBN_SELCHANGE) {
  198.                 return FALSE;
  199.             }
  200.             iprop = (int)SendDlgItemMessage(hDlg, PROP_NAME, CB_GETCURSEL, 0, 0L);
  201.             if (iprop == CB_ERR) {
  202.             return FALSE;
  203.             }
  204.             /* now look up entry in gsview.ini */
  205.             /* and update PROP_VALUE list box */
  206.             strcpy(section, device);
  207.             strcat(section, " values");
  208.             GetPrivateProfileString(section, propitem[iprop].name, "", buf, sizeof(buf)-2, INIFILE);
  209.             buf[strlen(buf)+1] = '\0';    /* put double NULL at end */
  210.             SendDlgItemMessage(hDlg, PROP_VALUE, CB_RESETCONTENT, 0, 0L);
  211.             SendDlgItemMessage(hDlg, PROP_VALUE, CB_ADDSTRING, 0, 
  212.             (LPARAM)((LPSTR)not_defined));
  213.             p = buf;
  214.             if (*p != '\0') {
  215.               EnableWindow(GetDlgItem(hDlg, PROP_VALUE), TRUE);
  216.               while (*p!='\0') {
  217.             value = p;
  218.             while ((*p!='\0') && (*p!=','))
  219.                 p++;
  220.             *p++ = '\0';
  221.             SendDlgItemMessage(hDlg, PROP_VALUE, CB_ADDSTRING, 0, 
  222.                 (LPARAM)((LPSTR)value));
  223.               }
  224.             }
  225.             SendDlgItemMessage(hDlg, PROP_VALUE, CB_SELECTSTRING, -1, (LPARAM)(LPSTR)propitem[iprop].value);
  226.             SetDlgItemText(hDlg, PROP_VALUE, propitem[iprop].value);
  227.             return FALSE;
  228.         case PROP_VALUE:
  229.             if (notify_message == CBN_SELCHANGE) {
  230.             iprop = (int)SendDlgItemMessage(hDlg, PROP_NAME, CB_GETCURSEL, 0, 0L);
  231.             if (iprop == CB_ERR)
  232.                 return FALSE;
  233.             ivalue = (int)SendDlgItemMessage(hDlg, PROP_VALUE, CB_GETCURSEL, 0, 0L);
  234.             if (ivalue == CB_ERR)
  235.                 return FALSE;
  236.             SendDlgItemMessage(hDlg, PROP_VALUE, CB_GETLBTEXT, ivalue, (LPARAM)(LPSTR)propitem[iprop].value);
  237.             }
  238.             if (notify_message == CBN_EDITCHANGE) {
  239.             iprop = (int)SendDlgItemMessage(hDlg, PROP_NAME, CB_GETCURSEL, 0, 0L);
  240.             if (iprop == CB_ERR)
  241.                 return FALSE;
  242.             GetDlgItemText(hDlg, PROP_VALUE, (LPSTR)propitem[iprop].value, sizeof(propitem->value));
  243.             }
  244.             return FALSE;
  245.         case PROP_EDIT:
  246.             load_string(IDS_TOPICEDITPROP, szHelpTopic, sizeof(szHelpTopic));
  247.             iprop = (int)SendDlgItemMessage(hDlg, PROP_NAME, CB_GETCURSEL, 0, 0L);
  248.             editpropname[0] = '\0';
  249.             if (iprop != CB_ERR)
  250.             strcpy(editpropname, propitem[iprop].name);
  251. #ifdef __WIN32__
  252.             DialogBoxParam( phInstance, "EditPropDlgBox", hDlg, EditPropDlgProc, (LPARAM)device);
  253. #else
  254.             {DLGPROC lpProcProp;
  255.             lpProcProp = (DLGPROC)MakeProcInstance((FARPROC)EditPropDlgProc, phInstance);
  256.             DialogBoxParam( phInstance, "EditPropDlgBox", hDlg, lpProcProp, (LPARAM)device);
  257.             FreeProcInstance((FARPROC)lpProcProp);
  258.             }
  259. #endif
  260.             free((char *)propitem);
  261.             SendMessage(hDlg, WM_INITDIALOG, (WPARAM)hDlg, (LPARAM)device);
  262.             load_string(IDS_TOPICPROP, szHelpTopic, sizeof(szHelpTopic));
  263.             SendDlgItemMessage(hDlg, IDOK, BM_SETSTYLE, 
  264.                 (WPARAM)BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
  265.             SendDlgItemMessage(hDlg, PROP_EDIT, BM_SETSTYLE, 
  266.                 (WPARAM)BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  267.             return FALSE;
  268.         case PROP_NEW:
  269.             load_string(IDS_TOPICEDITPROP, szHelpTopic, sizeof(szHelpTopic));
  270.             editpropname[0] = '\0';
  271. #ifdef __WIN32__
  272.             DialogBoxParam( phInstance, "EditPropDlgBox", hDlg, EditPropDlgProc, (LPARAM)device);
  273. #else
  274.             {DLGPROC lpProcProp;
  275.             lpProcProp = (DLGPROC)MakeProcInstance((FARPROC)EditPropDlgProc, phInstance);
  276.             DialogBoxParam( phInstance, "EditPropDlgBox", hDlg, lpProcProp, (LPARAM)device);
  277.             FreeProcInstance((FARPROC)lpProcProp);
  278.             }
  279. #endif
  280.             free((char *)propitem);
  281.             SendMessage(hDlg, WM_INITDIALOG, (WPARAM)hDlg, (LPARAM)device);
  282.             load_string(IDS_TOPICPROP, szHelpTopic, sizeof(szHelpTopic));
  283.             SendDlgItemMessage(hDlg, IDOK, BM_SETSTYLE, 
  284.                 (WPARAM)BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
  285.             SendDlgItemMessage(hDlg, PROP_NEW, BM_SETSTYLE, 
  286.                 (WPARAM)BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  287.             return FALSE;
  288.         case IDOK:
  289.             for (iprop=0; propitem[iprop].name[0]; iprop++) {
  290.             WritePrivateProfileString(device, propitem[iprop].name, propitem[iprop].value, INIFILE);
  291.             }
  292.             strcpy(section, device);
  293.             strcat(section, " PageOffset");
  294.             GetDlgItemText(hDlg, PROP_XOFFSET, buf, sizeof(buf-2));
  295.             WritePrivateProfileString(section, "X", buf, INIFILE);
  296.             GetDlgItemText(hDlg, PROP_YOFFSET, buf, sizeof(buf-2));
  297.             WritePrivateProfileString(section, "Y", buf, INIFILE);
  298.             free((char *)propitem);
  299.             EndDialog(hDlg, TRUE);
  300.             return TRUE;
  301.         case IDCANCEL:
  302.             free((char *)propitem);
  303.             EndDialog(hDlg, FALSE);
  304.             return TRUE;
  305.         }
  306.         break;
  307.     }
  308.     return FALSE;
  309. }
  310.  
  311.  
  312. #ifdef OLD
  313. /* dialog box for selecting printer device and resolution */
  314. BOOL CALLBACK _export
  315. DeviceDlgProc(HWND hDlg, UINT wmsg, WPARAM wParam, LPARAM lParam)
  316. {
  317.     char buf[128];
  318.     int idevice;
  319.     WORD notify_message;
  320.     char *p;
  321.     char *res;
  322.     int numentry;
  323.     char entry[MAXSTR];
  324.     struct prop_item_s *proplist;
  325.  
  326.     switch (wmsg) {
  327.         case WM_INITDIALOG:
  328.         p = get_devices();
  329.         res = p;    /* save for free() */
  330.         for (numentry=0; p!=(char *)NULL && strlen(p)!=0; numentry++) {
  331.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_ADDSTRING, 0, 
  332.             (LPARAM)((LPSTR)p));
  333.             p += strlen(p) + 1;
  334.         }
  335.         free(res);
  336.         if (SendDlgItemMessage(hDlg, DEVICE_NAME, CB_SELECTSTRING, 0, (LPARAM)(LPSTR)option.device_name)
  337.             == CB_ERR)
  338.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_SETCURSEL, 0, 0L);
  339.         /* force update of DEVICE_RES */
  340.         SendDlgNotification(hDlg, DEVICE_NAME, CBN_SELCHANGE);
  341.         if (SendDlgItemMessage(hDlg, DEVICE_RES, CB_SELECTSTRING, 0, (LPARAM)(LPSTR)option.device_resolution)
  342.             == CB_ERR)
  343.             SendDlgItemMessage(hDlg, DEVICE_RES, CB_SETCURSEL, 0, 0L);
  344.         return TRUE;
  345.         case WM_COMMAND:
  346.         notify_message = GetNotification(wParam,lParam);
  347.         switch (LOWORD(wParam)) {
  348.             case ID_HELP:
  349.                 SendMessage(hwndimg, help_message, 0, 0L);
  350.                 return(FALSE);
  351.             case DEVICE_NAME:
  352.             if (notify_message != CBN_SELCHANGE) {
  353.                 return FALSE;
  354.             }
  355.             idevice = (int)SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETCURSEL, 0, 0L);
  356.             if (idevice == CB_ERR) {
  357.                 return FALSE;
  358.             }
  359.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETLBTEXT, idevice, (LPARAM)(LPSTR)entry);
  360.             if ( (proplist = get_properties(entry)) != (struct prop_item_s *)NULL ) {
  361.                     free((char *)proplist);
  362.                 EnableWindow(GetDlgItem(hDlg, DEVICE_PROP), TRUE);
  363.             }
  364.             else
  365.                 EnableWindow(GetDlgItem(hDlg, DEVICE_PROP), FALSE);
  366.             /* now look up entry in gsview.ini */
  367.             /* and update DEVICE_RES list box */
  368.             GetPrivateProfileString(DEVSECTION, entry, "", buf, sizeof(buf)-2, INIFILE);
  369.             buf[strlen(buf)+1] = '\0';    /* double NULL at end */
  370.                 SendDlgItemMessage(hDlg, DEVICE_RES, CB_RESETCONTENT, 0, 0L);
  371.             p = buf;
  372.             if (*p == '\0') {
  373.                 /* no resolutions can be set */
  374.                 EnableWindow(GetDlgItem(hDlg, DEVICE_RES), FALSE);
  375.                 EnableWindow(GetDlgItem(hDlg, DEVICE_RESTEXT), FALSE);
  376.             }
  377.             else {
  378.               EnableWindow(GetDlgItem(hDlg, DEVICE_RES), TRUE);
  379.               EnableWindow(GetDlgItem(hDlg, DEVICE_RESTEXT), TRUE);
  380.               while (*p!='\0') {
  381.                 res = p;
  382.                 while ((*p!='\0') && (*p!=','))
  383.                 p++;
  384.                 *p++ = '\0';
  385.                     SendDlgItemMessage(hDlg, DEVICE_RES, CB_ADDSTRING, 0, 
  386.                     (LPARAM)((LPSTR)res));
  387.               }
  388.             }
  389.             SendDlgItemMessage(hDlg, DEVICE_RES, CB_SETCURSEL, 0, 0L);
  390.             if (SendDlgItemMessage(hDlg, DEVICE_RES, CB_GETLBTEXT, 0, (LPARAM)(LPSTR)buf)
  391.                 != CB_ERR)
  392.                     SetDlgItemText(hDlg, DEVICE_RES, buf);
  393.             return FALSE;
  394.             case DEVICE_RES:
  395.             /* don't have anything to do */
  396.             return FALSE;
  397.             case DEVICE_PROP:
  398.             idevice = (int)SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETCURSEL, 0, 0L);
  399.             if (idevice == CB_ERR) {
  400.                 return FALSE;
  401.             }
  402.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETLBTEXT, idevice, (LPARAM)(LPSTR)entry);
  403.             if ( (proplist = get_properties(entry)) != (struct prop_item_s *)NULL ) {
  404. #ifndef __WIN32__
  405.                     DLGPROC lpProcProp;
  406. #endif
  407.                     free((char *)proplist);
  408.                 LoadString(phInstance, IDS_TOPICPRINT, szHelpTopic, sizeof(szHelpTopic));
  409. #ifdef __WIN32__
  410.                 DialogBoxParam( phInstance, "PropDlgBox", hDlg, PropDlgProc, (LPARAM)entry);
  411. #else
  412.                 lpProcProp = (DLGPROC)MakeProcInstance((FARPROC)PropDlgProc, phInstance);
  413.                 DialogBoxParam( phInstance, "PropDlgBox", hDlg, lpProcProp, (LPARAM)entry);
  414.                 FreeProcInstance((FARPROC)lpProcProp);
  415. #endif
  416.             }
  417.             else
  418.                 play_sound(SOUND_ERROR);
  419.             return FALSE;
  420.             case IDOK:
  421.             /* save device name and resolution */
  422.                 GetDlgItemText(hDlg, DEVICE_NAME, option.device_name, sizeof(option.device_name));
  423.                 GetDlgItemText(hDlg, DEVICE_RES, option.device_resolution, sizeof(option.device_resolution));
  424.             EndDialog(hDlg, TRUE);
  425.             return TRUE;
  426.             case IDCANCEL:
  427.             EndDialog(hDlg, FALSE);
  428.             return TRUE;
  429.         }
  430.         break;
  431.     }
  432.     return FALSE;
  433. }
  434. #else
  435. char *device_queue_list;
  436. int device_to_file;
  437. int device_queue_index;
  438.  
  439. /* dialog box for selecting printer device and resolution */
  440. BOOL CALLBACK _export
  441. DeviceDlgProc(HWND hDlg, UINT wmsg, WPARAM wParam, LPARAM lParam)
  442. {
  443.     char buf[128];
  444.     int i, idevice;
  445.     WORD notify_message;
  446.     char *p;
  447.     char *res;
  448.     char entry[MAXSTR];
  449.     struct prop_item_s *proplist;
  450. #ifndef __WIN32__
  451.     static DLGPROC lpProcPage;
  452. #endif
  453.  
  454.     switch (wmsg) {
  455.         case WM_INITDIALOG:
  456. #ifndef __WIN32__
  457.         lpProcPage = (DLGPROC)MakeProcInstance((FARPROC)PageDlgProc, phInstance);
  458. #endif
  459.         p = get_devices();
  460.         res = p;    /* save for free() */
  461.         while ( p!=(char *)NULL && strlen(p)!=0) {
  462.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_ADDSTRING, 0, 
  463.             (LPARAM)((LPSTR)p));
  464.             p += strlen(p) + 1;
  465.         }
  466.         free(res);
  467.         if (SendDlgItemMessage(hDlg, DEVICE_NAME, CB_SELECTSTRING, 0, (LPARAM)(LPSTR)option.device_name)
  468.             == CB_ERR)
  469.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_SETCURSEL, 0, 0L);
  470.         /* force update of DEVICE_RES */
  471.         SendDlgNotification(hDlg, DEVICE_NAME, CBN_SELCHANGE);
  472.         if (SendDlgItemMessage(hDlg, DEVICE_RES, CB_SELECTSTRING, 0, (LPARAM)(LPSTR)option.device_resolution)
  473.             == CB_ERR)
  474.             SendDlgItemMessage(hDlg, DEVICE_RES, CB_SETCURSEL, 0, 0L);
  475.         /* insert queue list */
  476.         p = device_queue_list;
  477.         device_queue_index = 0;
  478.             idevice = 0;
  479.         while (*p) {
  480.             if ( strcmp(p, option.printer_port) == 0 )
  481.                 device_queue_index = idevice;
  482.             SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM)p);
  483.             p += lstrlen(p)+1;
  484.             idevice++;
  485.         }
  486.             SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, device_queue_index, (LPARAM)0);
  487.         /* fill in page list box */
  488.         if ( (doc != (PSDOC *)NULL) && (doc->numpages != 0)) {
  489.             page_list.current = psfile.pagenum-1;
  490.             page_list.multiple = TRUE;
  491. #ifdef __WIN32__
  492.             PageDlgProc(hDlg, wmsg, wParam, lParam);
  493. #else
  494.             CallWindowProc((WNDPROC)lpProcPage, hDlg, wmsg, wParam, lParam);
  495. #endif
  496.         }
  497.         else {
  498.             page_list.multiple = FALSE;
  499.             EnableWindow(GetDlgItem(hDlg, PAGE_ALL), FALSE);
  500.             EnableWindow(GetDlgItem(hDlg, PAGE_ODD), FALSE);
  501.             EnableWindow(GetDlgItem(hDlg, PAGE_EVEN), FALSE);
  502.             SendDlgItemMessage(hDlg, PAGE_LIST, LB_ADDSTRING, 0, 
  503.             (LPARAM)((LPSTR)"All"));
  504.             EnableWindow(GetDlgItem(hDlg, PAGE_LISTTEXT), FALSE);
  505.             EnableWindow(GetDlgItem(hDlg, PAGE_LIST), FALSE);
  506.         }
  507.         /* set Print to File check box */
  508.         if (device_to_file) {
  509.             SendDlgItemMessage(hDlg, SPOOL_TOFILE, BM_SETCHECK, 1, 0);
  510.             EnableWindow(GetDlgItem(hDlg, SPOOL_PORT), FALSE);
  511.             EnableWindow(GetDlgItem(hDlg, SPOOL_PORTTEXT), FALSE);
  512.         }
  513.         return TRUE;
  514.         case WM_COMMAND:
  515.         notify_message = GetNotification(wParam,lParam);
  516.         switch (LOWORD(wParam)) {
  517.             case PAGE_LIST:
  518.             case SPOOL_PORT:
  519.             if (notify_message == LBN_DBLCLK)
  520.                 PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
  521.             return FALSE;
  522.             case SPOOL_TOFILE:
  523.             if (notify_message == BN_CLICKED) {
  524.                     i = (int)SendDlgItemMessage(hDlg, SPOOL_TOFILE, BM_GETCHECK, 0, 0);
  525.                 /* toggle state */
  526.                 i = (i == 0) ? 1 : 0;
  527.                 SendDlgItemMessage(hDlg, SPOOL_TOFILE, BM_SETCHECK, i, 0);
  528.                 if (i) {  /* save selection */
  529.                 device_queue_index = (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L);
  530.                 }
  531.                 /* can't clear selection */
  532.                 EnableWindow(GetDlgItem(hDlg, SPOOL_PORT), (i ? FALSE : TRUE));
  533.                 EnableWindow(GetDlgItem(hDlg, SPOOL_PORTTEXT), (i ? FALSE : TRUE));
  534.             }
  535.             return FALSE;
  536.             case ID_HELP:
  537.                 SendMessage(hwndimg, help_message, 0, 0L);
  538.                 return FALSE;
  539.             case DEVICE_NAME:
  540.             if (notify_message != CBN_SELCHANGE) {
  541.                 return FALSE;
  542.             }
  543.             idevice = (int)SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETCURSEL, 0, 0L);
  544.             if (idevice == CB_ERR) {
  545.                 return FALSE;
  546.             }
  547.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETLBTEXT, idevice, (LPARAM)(LPSTR)entry);
  548.             if ( (proplist = get_properties(entry)) != (struct prop_item_s *)NULL ) {
  549.                     free((char *)proplist);
  550.                 EnableWindow(GetDlgItem(hDlg, DEVICE_PROP), TRUE);
  551.             }
  552.             else
  553.                 EnableWindow(GetDlgItem(hDlg, DEVICE_PROP), FALSE);
  554.             /* now look up entry in gsview.ini */
  555.             /* and update DEVICE_RES list box */
  556.             GetPrivateProfileString(DEVSECTION, entry, "", buf, sizeof(buf)-2, INIFILE);
  557.             buf[strlen(buf)+1] = '\0';    /* double NULL at end */
  558.                 SendDlgItemMessage(hDlg, DEVICE_RES, CB_RESETCONTENT, 0, 0L);
  559.             p = buf;
  560.             if (*p == '\0') {
  561.                 /* no resolutions can be set */
  562.                 EnableWindow(GetDlgItem(hDlg, DEVICE_RES), FALSE);
  563.                 EnableWindow(GetDlgItem(hDlg, DEVICE_RESTEXT), FALSE);
  564.             }
  565.             else {
  566.               EnableWindow(GetDlgItem(hDlg, DEVICE_RES), TRUE);
  567.               EnableWindow(GetDlgItem(hDlg, DEVICE_RESTEXT), TRUE);
  568.               while (*p!='\0') {
  569.                 res = p;
  570.                 while ((*p!='\0') && (*p!=','))
  571.                 p++;
  572.                 *p++ = '\0';
  573.                     SendDlgItemMessage(hDlg, DEVICE_RES, CB_ADDSTRING, 0, 
  574.                     (LPARAM)((LPSTR)res));
  575.               }
  576.             }
  577.             SendDlgItemMessage(hDlg, DEVICE_RES, CB_SETCURSEL, 0, 0L);
  578.             if (SendDlgItemMessage(hDlg, DEVICE_RES, CB_GETLBTEXT, 0, (LPARAM)(LPSTR)buf)
  579.                 != CB_ERR)
  580.                     SetDlgItemText(hDlg, DEVICE_RES, buf);
  581.             return FALSE;
  582.             case DEVICE_RES:
  583.             /* don't have anything to do */
  584.             return FALSE;
  585.             case DEVICE_PROP:
  586.             idevice = (int)SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETCURSEL, 0, 0L);
  587.             if (idevice == CB_ERR) {
  588.                 return FALSE;
  589.             }
  590.             SendDlgItemMessage(hDlg, DEVICE_NAME, CB_GETLBTEXT, idevice, (LPARAM)(LPSTR)entry);
  591.             if ( (proplist = get_properties(entry)) != (struct prop_item_s *)NULL ) {
  592. #ifndef __WIN32__
  593.                     DLGPROC lpProcProp;
  594. #endif
  595.                     free((char *)proplist);
  596.                 LoadString(phInstance, IDS_TOPICPRINT, szHelpTopic, sizeof(szHelpTopic));
  597. #ifdef __WIN32__
  598.                 DialogBoxParam( phInstance, "PropDlgBox", hDlg, PropDlgProc, (LPARAM)entry);
  599. #else
  600.                 lpProcProp = (DLGPROC)MakeProcInstance((FARPROC)PropDlgProc, phInstance);
  601.                 DialogBoxParam( phInstance, "PropDlgBox", hDlg, lpProcProp, (LPARAM)entry);
  602.                 FreeProcInstance((FARPROC)lpProcProp);
  603. #endif
  604.             }
  605.             else
  606.                 play_sound(SOUND_ERROR);
  607.             return FALSE;
  608.             case PAGE_ALL:
  609.             case PAGE_EVEN:
  610.             case PAGE_ODD:
  611. #ifdef __WIN32__
  612.                 PageDlgProc(hDlg, wmsg, wParam, lParam);
  613. #else
  614.             CallWindowProc((WNDPROC)lpProcPage, hDlg, wmsg, wParam, lParam);
  615. #endif
  616.             return FALSE;
  617.             case IDOK:
  618.             /* save device name and resolution */
  619.                 GetDlgItemText(hDlg, DEVICE_NAME, option.device_name, sizeof(option.device_name));
  620.                 GetDlgItemText(hDlg, DEVICE_RES, option.device_resolution, sizeof(option.device_resolution));
  621.             /* get Print to File status */
  622.              device_to_file = (int)SendDlgItemMessage(hDlg, 
  623.                 SPOOL_TOFILE, BM_GETCHECK, 0, 0);
  624.             if (!device_to_file) {
  625.                 /* save queue name */
  626.                 SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETTEXT, 
  627.                 (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L),
  628.                 (LPARAM)(LPSTR)option.printer_port);
  629.             }
  630.             /* get pages */
  631.             if ((doc != (PSDOC *)NULL) && (doc->numpages != 0))
  632. #ifdef __WIN32__
  633.                 PageDlgProc(hDlg, wmsg, wParam, lParam);
  634. #else
  635.                 CallWindowProc((WNDPROC)lpProcPage, hDlg, wmsg, wParam, lParam);
  636. #endif
  637. #ifndef __WIN32__
  638.             FreeProcInstance((FARPROC)lpProcPage);
  639. #endif
  640.             EndDialog(hDlg, TRUE);
  641.             return TRUE;
  642.             case IDCANCEL:
  643.             EndDialog(hDlg, FALSE);
  644. #ifndef __WIN32__
  645.             FreeProcInstance((FARPROC)lpProcPage);
  646. #endif
  647.             return TRUE;
  648.         }
  649.         break;
  650.     }
  651.     return FALSE;
  652. }
  653.  
  654.  
  655. int
  656. get_device(int to_file)
  657. {
  658. int result;
  659. #ifndef __WIN32__
  660. DLGPROC lpProcDevice;
  661. #endif
  662. #define DEVICE_BUF_SIZE 4096
  663.     device_to_file = to_file;
  664.     device_queue_list = get_ports();
  665.     if (device_queue_list == (char *)NULL)
  666.     return FALSE;
  667.  
  668.     load_string(IDS_TOPICPRINT, szHelpTopic, sizeof(szHelpTopic));
  669. #ifdef __WIN32__
  670.     result = DialogBoxParam( phInstance, "DeviceDlgBox", hwndimg, DeviceDlgProc, (LPARAM)NULL);
  671. #else
  672.     lpProcDevice = (DLGPROC)MakeProcInstance((FARPROC)DeviceDlgProc, phInstance);
  673.     result = DialogBoxParam( phInstance, "DeviceDlgBox", hwndimg, lpProcDevice, (LPARAM)NULL);
  674.     FreeProcInstance((FARPROC)lpProcDevice);
  675. #endif
  676.     free(device_queue_list);
  677.     if (result != IDOK)
  678.     return FALSE;
  679.     return TRUE;
  680. }
  681.  
  682.  
  683. #endif
  684.  
  685.  
  686.  
  687. #pragma argsused
  688. /* Modeless dialog box - Cancel printing */
  689. BOOL CALLBACK _export
  690. CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  691. {
  692.     switch(message) {
  693.     case WM_INITDIALOG:
  694.         SetWindowText(hDlg, szAppName);
  695.         return TRUE;
  696.     case WM_COMMAND:
  697.         switch(LOWORD(wParam)) {
  698.         case IDCANCEL:
  699.             DestroyWindow(hDlg);
  700.             hDlgModeless = 0;
  701.             EndDialog(hDlg, 0);
  702.             return TRUE;
  703.         }
  704.     }
  705.     return FALSE;
  706. }
  707.  
  708. /* Dialog box to select printer port */
  709. BOOL CALLBACK _export
  710. SpoolDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  711. {
  712. LPSTR entry;
  713.     switch(message) {
  714.     case WM_INITDIALOG:
  715.         entry = (LPSTR)lParam;
  716.         while (*entry) {
  717.         SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM)entry);
  718.         entry += lstrlen(entry)+1;
  719.         }
  720.         if ( (*option.printer_port=='\0') ||
  721.         (SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SELECTSTRING, 0, (LPARAM)(LPSTR)option.printer_port)
  722.             == LB_ERR) )
  723.             SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, 0, (LPARAM)0);
  724.         return TRUE;
  725.     case WM_COMMAND:
  726.         switch(LOWORD(wParam)) {
  727.         case SPOOL_PORT:
  728. #ifdef __WIN32__
  729.             if (HIWORD(wParam)
  730. #else
  731.             if (HIWORD(lParam)
  732. #endif
  733.                            == LBN_DBLCLK)
  734.             PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
  735.             return FALSE;
  736.         case IDOK:
  737.             SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETTEXT, 
  738.             (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L),
  739.             (LPARAM)(LPSTR)option.printer_port);
  740.             EndDialog(hDlg, 1+(int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L));
  741.             return TRUE;
  742.         case IDCANCEL:
  743.             EndDialog(hDlg, 0);
  744.             return TRUE;
  745.         }
  746.     }
  747.     return FALSE;
  748. }
  749.  
  750. #ifdef __WIN32__
  751. char *
  752. get_queues(void)
  753. {
  754. int i;
  755. DWORD count, needed;
  756. PRINTER_INFO_1 *prinfo;
  757. char *enumbuffer;
  758. char *buffer;
  759. char *p;
  760.     /* enumerate all available printers */
  761.     EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &needed, &count);
  762.     enumbuffer = malloc(needed);
  763.     if (enumbuffer == (char *)NULL)
  764.     return FALSE;
  765.     if (!EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, (LPBYTE)enumbuffer, needed, &needed, &count)) {
  766.     char buf[256];
  767.     free(enumbuffer);
  768.     sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
  769.     gserror(0, buf, MB_ICONHAND, SOUND_ERROR);
  770.     return NULL;
  771.     }
  772.     prinfo = (PRINTER_INFO_1 *)enumbuffer;
  773.     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL) {
  774.     free(enumbuffer);
  775.     return NULL;
  776.     }
  777.     /* copy printer names to single buffer */
  778.     p = buffer;
  779.     for (i=0; i<count; i++) {
  780.     if (strlen(prinfo[i].pName) + 1 < (PORT_BUF_SIZE- (p-buffer))) {
  781.         strcpy(p, prinfo[i].pName);
  782.         p += strlen(p) + 1;
  783.     }
  784.     }
  785.     *p = '\0';    /* double null at end */
  786.     free(enumbuffer);
  787.     return buffer;
  788. }
  789.  
  790. /* return TRUE if queuename available */
  791. /* return FALSE if cancelled or error */
  792. /* if queue non-NULL, use as suggested queue */
  793. BOOL
  794. get_queuename(char *portname, char *queue)
  795. {
  796. char *buffer;
  797. char *p;
  798. int i, iport;
  799.  
  800.     buffer = get_queues();
  801.     if ( (queue == (char *)NULL) || (strlen(queue)==0) ) {
  802.     /* select a queue */
  803.     iport = DialogBoxParam(phInstance, "QueueDlgBox", hwndtext, SpoolDlgProc, (LPARAM)buffer);
  804.     if (!iport) {
  805.         free(buffer);
  806.         return FALSE;
  807.     }
  808.     p = buffer;
  809.     for (i=1; i<iport && strlen(p)!=0; i++)
  810.         p += lstrlen(p)+1;
  811.     /* prepend \\spool\ which is used by Ghostscript to distinguish */
  812.     /* real files from queues */
  813.     strcpy(portname, "\\\\spool\\");
  814.     strcat(portname, p);
  815.     }
  816.     else {
  817.     strcpy(portname, "\\\\spool\\");
  818.     strcat(portname, queue);
  819.     }
  820.  
  821.     free(buffer);
  822.     return TRUE;
  823. }
  824. #endif
  825.  
  826.  
  827. /* return TRUE if portname available */
  828. /* return FALSE if cancelled or error */
  829. /* if port non-NULL, use as suggested port */
  830. BOOL
  831. get_portname(char *portname, char *port)
  832. {
  833. char *buffer;
  834. char *p;
  835. int i, iport;
  836. char filename[MAXSTR];
  837. #ifdef __WIN32__
  838.     if (is_win95 || is_winnt)
  839.         return get_queuename(portname, port);
  840. #endif
  841.  
  842.         buffer = get_ports();
  843.     if ( (port == (char *)NULL) || (strlen(port)==0) ) {
  844.         if (buffer == (char *)NULL)
  845.         return NULL;
  846.         /* select a port */
  847.         iport = DialogBoxParam(phInstance, "SpoolDlgBox", hwndtext, SpoolDlgProc, (LPARAM)buffer);
  848.         if (!iport) {
  849.             free(buffer);
  850.             return FALSE;
  851.         }
  852.         p = buffer;
  853.         for (i=1; i<iport && strlen(p)!=0; i++)
  854.             p += lstrlen(p)+1;
  855.         strcpy(portname, p);
  856.     }
  857.     else
  858.         strcpy(portname, port);
  859.  
  860.     if (strlen(portname) == 0)
  861.         return FALSE;
  862.     if (strcmp(portname,"FILE:") == 0) {
  863.         strcpy(filename, "*.prn");
  864.         if (!get_filename(filename, TRUE, FILTER_ALL, IDS_PRINTFILE, IDS_TOPICPRINT)) {
  865.             free(buffer);
  866.             return FALSE;
  867.         }
  868.         strcpy(portname, filename);
  869.     }
  870. #ifdef NOTUSED
  871.     else {
  872.         portname[strlen(portname)-1] = '\0';  /* remove trailing colon */
  873.     }
  874. #endif
  875.     free(buffer);
  876.     return TRUE;
  877. }
  878.  
  879.  
  880. char *
  881. get_ports(void)
  882. {
  883. char *buffer;
  884. #ifdef __WIN32__
  885.     if (is_win95 || is_winnt)
  886.         return get_queues();
  887. #endif
  888.  
  889.     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL)
  890.         return NULL;
  891.     GetProfileString("ports", NULL, "", buffer, PORT_BUF_SIZE);
  892.     return buffer;
  893. }
  894.  
  895.  
  896.  
  897.  
  898. /******************************************************************/
  899. /* Print File to port or queue */
  900. /* port==NULL means prompt for port or queue with dialog box */
  901. int gp_printfile(char *filename, char *port);
  902.  
  903. /* This is messy because Microsoft changed the spooler interface */
  904. /* between Window 3.1 and Windows 95/NT */
  905. /* and didn't provide the spooler interface in Win32s */
  906.  
  907. /* This code requires several different versions */
  908. /* Win16: Use OpenJob etc. */
  909. int gp_printfile_win16(char *filename, char *port);
  910.  
  911. /* Win95, WinNT: Use OpenPrinter, WritePrinter etc. */
  912. int gp_printfile_win32(char *filename, char *port);
  913.  
  914. /* Win32s: Pass to Win16 spooler via gsv16spl.exe */
  915. int gp_printfile_gsv16spl(char *filename, char *port);
  916.  
  917. /* Currently not used, because Universal Thunk example code won't work */
  918. /* Use Win16 OpenJob via Universal Thunk */
  919. int gp_printfile_win32s(char *filename, char *port);
  920.  
  921. /* Currently not used, because it works on some PCs and not on others */
  922. /* This writes direct to a printer port */
  923. int gp_printfile_port(char *filename, char *port);
  924.  
  925. /* Currently not used, the following one tries to sneak code */
  926. /* through a Windows printer driver */
  927. /* This usually works for Epson compatible drivers, */
  928. /* but does not work for PostScript or Generic/Text only drivers */
  929. int gp_printfile_gdi32(char *filename, char *port);
  930.  
  931. int gp_printfile_test(char *filename, char *port);
  932.  
  933. int gp_printfile(char *filename, char *port)
  934. {
  935. #ifdef __WIN32__
  936.     if (is_win95 || is_winnt)
  937.     return gp_printfile_win32(filename, port);
  938. /*
  939.     return gp_printfile_win32s(filename, port);
  940.     return gp_printfile_port(filename, port);
  941. */
  942.     return gp_printfile_gsv16spl(filename, port);
  943. #else
  944.     /* Win16 */
  945.     return gp_printfile_win16(filename, port);
  946. #endif
  947.    
  948. }
  949.  
  950. #define PRINT_BUF_SIZE 16384u
  951.  
  952. #ifndef __WIN32__
  953. /* Win16 method using OpenJob etc. */
  954. int
  955. gp_printfile_win16(char *filename, char *port)
  956. {
  957. char *buffer;
  958. char portname[MAXSTR];
  959. HPJOB hJob;
  960. UINT count;
  961. FILE *f;
  962. int error = FALSE;
  963. DLGPROC lpfnCancelProc;
  964. long lsize;
  965. long ldone;
  966. char fmt[MAXSTR];
  967. char pcdone[10];
  968. MSG msg;
  969.  
  970.     if (!get_portname(portname, port))
  971.     return FALSE;
  972.  
  973.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
  974.     return FALSE;
  975.     
  976.     if ((f = fopen(filename, "rb")) == (FILE *)NULL) {
  977.     free(buffer);
  978.     return FALSE;
  979.     }
  980.     fseek(f, 0L, SEEK_END);
  981.     lsize = ftell(f);
  982.     if (lsize <= 0)
  983.     lsize = 1;
  984.     fseek(f, 0L, SEEK_SET);
  985.  
  986.     hJob = OpenJob(portname, filename, (HDC)NULL);
  987.     switch ((int)hJob) {
  988.     case SP_APPABORT:
  989.     case SP_ERROR:
  990.     case SP_OUTOFDISK:
  991.     case SP_OUTOFMEMORY:
  992.     case SP_USERABORT:
  993.         fclose(f);
  994.         free(buffer);
  995.         return FALSE;
  996.     }
  997.     if (StartSpoolPage(hJob) < 0)
  998.     error = TRUE;
  999.  
  1000.     lpfnCancelProc = (DLGPROC)MakeProcInstance((FARPROC)CancelDlgProc, phInstance);
  1001.     hDlgModeless = CreateDialog(phInstance, "CancelDlgBox", hwndimg, lpfnCancelProc);
  1002.     ldone = 0;
  1003.     LoadString(phInstance, IDS_CANCELDONE, fmt, sizeof(fmt));
  1004.  
  1005.     while (!error && hDlgModeless 
  1006.       && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0 ) {
  1007.     if (WriteSpool(hJob, buffer, count) < 0)
  1008.         error = TRUE;
  1009.     ldone += count;
  1010.     sprintf(pcdone, fmt, (int)(ldone * 100 / lsize));
  1011.     SetWindowText(GetDlgItem(hDlgModeless, CANCEL_PCDONE), pcdone);
  1012.     while (PeekMessage(&msg, hDlgModeless, 0, 0, PM_REMOVE)) {
  1013.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  1014.         TranslateMessage(&msg);
  1015.         DispatchMessage(&msg);
  1016.         }
  1017.     }
  1018.     }
  1019.     free(buffer);
  1020.     fclose(f);
  1021.  
  1022.     if (!hDlgModeless)
  1023.     error=TRUE;
  1024.     DestroyWindow(hDlgModeless);
  1025.     hDlgModeless = 0;
  1026.     FreeProcInstance((FARPROC)lpfnCancelProc);
  1027.     EndSpoolPage(hJob);
  1028.     if (error)
  1029.     DeleteJob(hJob, 0);
  1030.     else
  1031.     CloseJob(hJob);
  1032.     return !error;
  1033. }
  1034.  
  1035. #else /* __WIN32__ */
  1036.  
  1037. /* True Win32 method, using OpenPrinter, WritePrinter etc. */
  1038. int 
  1039. gp_printfile_win32(char *filename, char *port)
  1040. {
  1041. DWORD count;
  1042. char *buffer;
  1043. char portname[MAXSTR];
  1044. FILE *f;
  1045. HANDLE printer;
  1046. DOC_INFO_1 di;
  1047. DWORD written;
  1048.  
  1049.     if (!get_portname(portname, port))
  1050.     return FALSE;
  1051.     port = portname + 8;    /* skip over \\spool\ */
  1052.  
  1053.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
  1054.         return FALSE;
  1055.     
  1056.     if ((f = fopen(filename, "rb")) == (FILE *)NULL) {
  1057.     free(buffer);
  1058.     return FALSE;
  1059.     }
  1060.  
  1061.  
  1062.     /* open a printer */
  1063.     if (!OpenPrinter(port, &printer, NULL)) {
  1064.     char buf[256];
  1065.     sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
  1066.     gserror(0, buf, MB_ICONHAND, SOUND_ERROR);
  1067.     free(buffer);
  1068.     return FALSE;
  1069.     }
  1070.     /* from here until ClosePrinter, should AbortPrinter on error */
  1071.  
  1072.     di.pDocName = filename;
  1073.     di.pOutputFile = NULL;
  1074.     di.pDatatype = "RAW";  /* for available types see EnumPrintProcessorDatatypes */
  1075.     if (!StartDocPrinter(printer, 1, (LPBYTE)&di)) {
  1076.     char buf[256];
  1077.     sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
  1078.     gserror(0, buf, MB_ICONHAND, SOUND_ERROR);
  1079.     AbortPrinter(printer);
  1080.     free(buffer);
  1081.     return FALSE;
  1082.     }
  1083.    
  1084.  
  1085.     while ((count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0 ) {
  1086.     if (!WritePrinter(printer, (LPVOID)buffer, count, &written)) {
  1087.         free(buffer);
  1088.         fclose(f);
  1089.         AbortPrinter(printer);
  1090.         return FALSE;
  1091.     }
  1092.     }
  1093.     fclose(f);
  1094.     free(buffer);
  1095.  
  1096.     if (!EndDocPrinter(printer)) {
  1097.     char buf[256];
  1098.     sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
  1099.     gserror(0, buf, MB_ICONHAND, SOUND_ERROR);
  1100.     AbortPrinter(printer);
  1101.     return FALSE;
  1102.     }
  1103.  
  1104.     if (!ClosePrinter(printer)) {
  1105.     char buf[256];
  1106.     sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
  1107.     gserror(0, buf, MB_ICONHAND, SOUND_ERROR);
  1108.     return FALSE;
  1109.     }
  1110.     return TRUE;
  1111. }
  1112.  
  1113.  
  1114. #ifdef NOTUSED
  1115. /* Win32s */
  1116. /* try to load spool32.dll to get access to Win16 OpenJob etc. */
  1117. /* via Universal Thunk */
  1118. int
  1119. gp_printfile_win32s(char *filename, char *port)
  1120. {
  1121. HMODULE hlib_spool;
  1122. pfnOpenJob OpenJob;
  1123. pfnStartSpoolPage StartSpoolPage;
  1124. pfnEndSpoolPage EndSpoolPage;
  1125. pfnWriteSpool WriteSpool;
  1126. pfnCloseJob CloseJob;
  1127. pfnDeleteJob DeleteJob;
  1128.  
  1129. char *buffer;
  1130. char portname[MAXSTR];
  1131. HANDLE hJob;
  1132. UINT count;
  1133. FILE *f;
  1134. int error = FALSE;
  1135. long lsize;
  1136. long ldone;
  1137. char fmt[MAXSTR];
  1138. char pcdone[10];
  1139. MSG msg;
  1140.  
  1141.     hlib_spool = LoadLibrary("SPOOL32.DLL");
  1142.     if (hlib_spool == NULL)    /* if can't find it, try other method */
  1143.     return gp_printfile_port(filename, port);
  1144.  
  1145.     /* get pointers to all the routines */
  1146.     OpenJob = (pfnOpenJob)GetProcAddress(hlib_spool, "OpenJob");
  1147.     StartSpoolPage = (pfnStartSpoolPage)GetProcAddress(hlib_spool, "StartSpoolPage");
  1148.     EndSpoolPage = (pfnEndSpoolPage)GetProcAddress(hlib_spool, "EndSpoolPage");
  1149.     WriteSpool = (pfnWriteSpool)GetProcAddress(hlib_spool, "WriteSpool");
  1150.     CloseJob = (pfnCloseJob)GetProcAddress(hlib_spool, "CloseJob");
  1151.     DeleteJob = (pfnDeleteJob)GetProcAddress(hlib_spool, "DeleteJob");
  1152.  
  1153.     if (!get_portname(portname, port)) {
  1154.     FreeLibrary(hlib_spool);
  1155.     return FALSE;
  1156.     }
  1157.  
  1158.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL) {
  1159.     FreeLibrary(hlib_spool);
  1160.     return FALSE;
  1161.     }
  1162.     
  1163.     if ((f = fopen(filename, "rb")) == (FILE *)NULL) {
  1164.     FreeLibrary(hlib_spool);
  1165.     free(buffer);
  1166.     return FALSE;
  1167.     }
  1168.     fseek(f, 0L, SEEK_END);
  1169.     lsize = ftell(f);
  1170.     if (lsize <= 0)
  1171.     lsize = 1;
  1172.     fseek(f, 0L, SEEK_SET);
  1173.  
  1174.     hJob = OpenJob(portname, filename, (HDC)NULL);
  1175.     switch ((int)hJob) {
  1176.     case SP_APPABORT:
  1177.     case SP_ERROR:
  1178.     case SP_OUTOFDISK:
  1179.     case SP_OUTOFMEMORY:
  1180.     case SP_USERABORT:
  1181.         fclose(f);
  1182.         free(buffer);
  1183.         FreeLibrary(hlib_spool);
  1184.         return FALSE;
  1185.     }
  1186.     if (StartSpoolPage(hJob) < 0)
  1187.     error = TRUE;
  1188.  
  1189.     hDlgModeless = CreateDialog(phInstance, "CancelDlgBox", hwndimg, CancelDlgProc);
  1190.     ldone = 0;
  1191.     LoadString(phInstance, IDS_CANCELDONE, fmt, sizeof(fmt));
  1192.  
  1193.     while (!error && hDlgModeless 
  1194.       && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0 ) {
  1195.     if (WriteSpool(hJob, buffer, (WORD)count) < 0)
  1196.         error = TRUE;
  1197.     ldone += count;
  1198.     sprintf(pcdone, fmt, (int)(ldone * 100 / lsize));
  1199.     SetWindowText(GetDlgItem(hDlgModeless, CANCEL_PCDONE), pcdone);
  1200.     while (PeekMessage(&msg, hDlgModeless, 0, 0, PM_REMOVE)) {
  1201.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  1202.         TranslateMessage(&msg);
  1203.         DispatchMessage(&msg);
  1204.         }
  1205.     }
  1206.     }
  1207.     free(buffer);
  1208.     fclose(f);
  1209.  
  1210.     if (!hDlgModeless)
  1211.     error=TRUE;
  1212.     DestroyWindow(hDlgModeless);
  1213.     hDlgModeless = 0;
  1214.     EndSpoolPage(hJob);
  1215.     if (error)
  1216.     DeleteJob(hJob, 0);
  1217.     else
  1218.     CloseJob(hJob);
  1219.     FreeLibrary(hlib_spool);
  1220.     return !error;
  1221.  
  1222. }
  1223.  
  1224.  
  1225. /* Open port as a file */
  1226. /* Works under Win16 and Win32, but not needed under Win16 */
  1227. int
  1228. gp_printfile_port(char *filename, char *port)
  1229. {
  1230. /* Get printer port list from win.ini, then copy to \\.\port */
  1231. char *buffer;
  1232. char portname[MAXSTR];
  1233. FILE *f;
  1234. long count;
  1235. int error = FALSE;
  1236. long lsize;
  1237. long ldone;
  1238. char pcdone[20];
  1239. MSG msg;
  1240. FILE *outfile;
  1241.  
  1242.     if (!get_portname(portname, port))
  1243.         return FALSE;
  1244.  
  1245.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
  1246.         return FALSE;
  1247.  
  1248.     if ((f = fopen(filename, "rb")) == (FILE *)NULL) {
  1249.         free(buffer);
  1250.         return FALSE;
  1251.     }
  1252.     fseek(f, 0L, SEEK_END);
  1253.     lsize = ftell(f);
  1254.     if (lsize <= 0)
  1255.         lsize = 1;
  1256.     fseek(f, 0L, SEEK_SET);
  1257.  
  1258.     
  1259.     outfile = fopen(portname, "wb");
  1260.     if (outfile == (FILE *)NULL) {
  1261.         fclose(f);
  1262.         free(buffer);
  1263.         return FALSE;
  1264.     }
  1265.  
  1266.     hDlgModeless = CreateDialog(phInstance, "CancelDlgBox", hwndtext, CancelDlgProc);
  1267.     ldone = 0;
  1268.  
  1269.     while (!error && hDlgModeless 
  1270.       && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0 ) {
  1271.         if (fwrite(buffer, 1, count, outfile) < count)
  1272.         error = TRUE;
  1273.         ldone += count;
  1274.         sprintf(pcdone, "%d %%done", (int)(ldone * 100 / lsize));
  1275.         SetWindowText(GetDlgItem(hDlgModeless, CANCEL_PCDONE), pcdone);
  1276.         while (PeekMessage(&msg, hDlgModeless, 0, 0, PM_REMOVE)) {
  1277.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  1278.             TranslateMessage(&msg);
  1279.             DispatchMessage(&msg);
  1280.           }
  1281.           }
  1282.       }
  1283.     free(buffer);
  1284.     fclose(f);
  1285.  
  1286.     if (!hDlgModeless)
  1287.         error=TRUE;
  1288.     DestroyWindow(hDlgModeless);
  1289.     hDlgModeless = 0;
  1290.     fclose(outfile);
  1291.     return !error;
  1292. }
  1293. #endif
  1294.  
  1295. /* Start a 16-bit application gsv16spl.exe and pass printer data in */
  1296. /* global memory.  gsv16spl.exe then uses 16-bit spooler functions. */
  1297. /* Only works under Win16 and Win32s */
  1298. /* Intended for Win32s where 16-bit spooler functions are not available */
  1299. /* and Win32 spooler functions are not implemented. */
  1300. int
  1301. gp_printfile_gsv16spl(char *filename, char *port)
  1302. {
  1303. /* Get printer port list from win.ini */
  1304. char *buffer;
  1305. char portname[MAXSTR];
  1306. FILE *f;
  1307. unsigned int count;
  1308. int error = FALSE;
  1309. long lsize;
  1310. long ldone;
  1311. char pcdone[20];
  1312. MSG msg;
  1313. DLGPROC lpfnCancelProc;
  1314. HINSTANCE hinst;
  1315. char command[MAXSTR];
  1316. HGLOBAL hmem;
  1317. LPBYTE data;
  1318.  
  1319.     if (!get_portname(portname, port))
  1320.         return FALSE;
  1321.  
  1322.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
  1323.         return FALSE;
  1324.  
  1325.     hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, PRINT_BUF_SIZE+sizeof(WORD));
  1326.     if (hmem == (HGLOBAL)NULL) {
  1327.         free(buffer);
  1328.         gserror(0, "Can't allocate global memory for gsv16spl", NULL, SOUND_ERROR);
  1329.         return FALSE;
  1330.     }
  1331.  
  1332.     if ((f = fopen(filename, "rb")) == (FILE *)NULL) {
  1333.         free(buffer);
  1334.         GlobalFree(hmem);
  1335.         return FALSE;
  1336.     }
  1337.     fseek(f, 0L, SEEK_END);
  1338.     lsize = ftell(f);
  1339.     if (lsize <= 0)
  1340.         lsize = 1;
  1341.     fseek(f, 0L, SEEK_SET);
  1342.  
  1343.     data = GlobalLock(hmem);
  1344.     lstrcpy(((LPSTR)data)+2, portname);
  1345.     *((LPWORD)data) = (WORD)(lstrlen(portname)+1);
  1346.     GlobalUnlock(hmem);
  1347.     
  1348.     strcpy(command, szExePath);
  1349.     strcat(command, "gsv16spl.exe");
  1350.     sprintf(command+strlen(command), " %lu", (unsigned long)hwndimg);
  1351.     hinst = (HINSTANCE)WinExec(command, SW_SHOWMINNOACTIVE);
  1352. #ifdef __WIN32__
  1353.     if (hinst == NULL)
  1354. #else
  1355.     if (hinst < HINSTANCE_ERROR)
  1356. #endif
  1357.     {
  1358.         fclose(f);
  1359.         free(buffer);
  1360.         GlobalFree(hmem);
  1361.         gserror(IDS_CANNOTRUN, command, MB_ICONSTOP, SOUND_ERROR);
  1362.         return FALSE;
  1363.     }
  1364.     if (hwndspl == (HWND)NULL) {
  1365.         fclose(f);
  1366.         free(buffer);
  1367.         GlobalFree(hmem);
  1368.         gserror(0, "gsv16spl didn't give us a window handle", NULL, SOUND_ERROR);
  1369.         return FALSE;    /* gsv16spl didn't SendMessage to us */
  1370.     }
  1371.  
  1372.     if (!SendMessage(hwndspl, WM_GSV16SPL, 0, (LPARAM)hmem)) {
  1373.         fclose(f);
  1374.         free(buffer);
  1375.         GlobalFree(hmem);
  1376.         gserror(0, "gsv16spl couldn't start printer job", NULL, SOUND_ERROR);
  1377.         return FALSE;
  1378.     }
  1379.  
  1380.  
  1381. #ifdef __WIN32__
  1382.     hDlgModeless = CreateDialog(phInstance, "CancelDlgBox", hwndtext, CancelDlgProc);
  1383. #else
  1384.         lpfnCancelProc = (DLGPROC)MakeProcInstance((FARPROC)CancelDlgProc, phInstance);
  1385.         hDlgModeless = CreateDialog(phInstance, "CancelDlgBox", hwndimg, lpfnCancelProc);
  1386. #endif
  1387.     ldone = 0;
  1388.  
  1389.     data = GlobalLock(hmem);
  1390.     while (!error && hDlgModeless 
  1391.       && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0 ) {
  1392.         *((LPWORD)data) = (WORD)count;
  1393. #ifdef __WIN32__
  1394.         memcpy(((LPSTR)data)+2, buffer, count);
  1395. #else
  1396.         _fmemcpy(((LPSTR)data)+2, buffer, count);
  1397. #endif
  1398.         GlobalUnlock(hmem);
  1399.         if (!SendMessage(hwndspl, WM_GSV16SPL, 0, (LPARAM)hmem))
  1400.         error = TRUE;
  1401.         ldone += count;
  1402.         sprintf(pcdone, "%d %%done", (int)(ldone * 100 / lsize));
  1403.         SetWindowText(GetDlgItem(hDlgModeless, CANCEL_PCDONE), pcdone);
  1404.         while (PeekMessage(&msg, hDlgModeless, 0, 0, PM_REMOVE)) {
  1405.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  1406.             TranslateMessage(&msg);
  1407.             DispatchMessage(&msg);
  1408.           }
  1409.           }
  1410.         data = GlobalLock(hmem);
  1411.       }
  1412.     fclose(f);
  1413.  
  1414.     if (!hDlgModeless)
  1415.         error=TRUE;
  1416.  
  1417.     if (error)
  1418.         *((LPWORD)data) = 0xffff;    /* abort */
  1419.     else
  1420.         *((LPWORD)data) = 0;    /* EOF */
  1421.     GlobalUnlock(hmem);
  1422.         SendMessage(hwndspl, WM_GSV16SPL, 0, (LPARAM)hmem);
  1423.     GlobalFree(hmem);
  1424.     free(buffer);
  1425.  
  1426.     DestroyWindow(hDlgModeless);
  1427.     hDlgModeless = 0;
  1428. #ifndef __WIN32__
  1429.     FreeProcInstance((FARPROC)lpfnCancelProc);
  1430. #endif
  1431.     return !error;
  1432. }
  1433.  
  1434.  
  1435. #endif /* __WIN32__ */
  1436.  
  1437.  
  1438. /* cleanup print temporary files */
  1439. void
  1440. print_cleanup(void)
  1441. {
  1442.     if ((pcfname[0] != '\0') && !debug)
  1443.         unlink(pcfname);
  1444.     pcfname[0] = '\0';
  1445.     if ((pfname[0] != '\0') && !debug)
  1446.         unlink(pfname);
  1447.     pfname[0] = '\0';
  1448. }
  1449.  
  1450.  
  1451. /* print a range of pages using a Ghostscript device */
  1452. void
  1453. gsview_print(BOOL to_file)
  1454. {
  1455.     char command[MAXSTR+MAXSTR];
  1456.     
  1457.     if (psfile.name[0] == '\0') {
  1458.         gserror(IDS_NOTOPEN, NULL, MB_ICONEXCLAMATION, SOUND_NOTOPEN);
  1459.         return;
  1460.     }
  1461.  
  1462.     LoadString(phInstance, IDS_TOPICPRINT, szHelpTopic, sizeof(szHelpTopic));
  1463.     
  1464.     if (!get_device(to_file))
  1465.         return;
  1466.  
  1467.     info_wait(IDS_WAITGSCLOSE);
  1468.     gs_close();    /* we need a new Ghostscript */
  1469.     info_wait(IDS_NOWAIT);
  1470.  
  1471.     if (!gsview_cprint(device_to_file, pcfname, pfname))
  1472.         return;
  1473.  
  1474.     sprintf(command,"%s %s -sGSVIEW=%u @%s", option.gsexe, option.gsother,
  1475.         (unsigned int)hwndimg, pfname);
  1476.  
  1477.     if (strlen(command) > 126) {
  1478.         /* command line too long */
  1479.         gserror(IDS_TOOLONG, command, MB_ICONSTOP, SOUND_ERROR);
  1480.         unlink(pfname);
  1481.         pfname[0] = '\0';
  1482.         gsprog.hinst = (HINSTANCE)NULL;
  1483.         return;
  1484.     }
  1485.     info_wait(IDS_WAITGSOPEN);
  1486.     gsprog.hinst = (HINSTANCE)WinExec(command, SW_SHOWMINNOACTIVE);
  1487.  
  1488. #ifdef __WIN32__
  1489.     if (gsprog.hinst == NULL)
  1490. #else
  1491.     if (gsprog.hinst < HINSTANCE_ERROR)
  1492. #endif
  1493.     {
  1494.         gserror(IDS_CANNOTRUN, command, MB_ICONSTOP, SOUND_ERROR);
  1495.         unlink(pfname);
  1496.         pfname[0] = '\0';
  1497.         info_wait(IDS_NOWAIT);
  1498.         gsprog.hinst = (HINSTANCE)NULL;
  1499.         return;
  1500.     }
  1501.  
  1502. /*
  1503.     set_timer(timeout*pages);
  1504. */
  1505.     info_wait(IDS_WAITPRINT);
  1506.     return;
  1507. }
  1508.  
  1509.  
  1510.